package calcs;

import gui.ErrorMessage;
import gui.MyFrame;
import gui.data.D2.PolygonOutputGui;
import static util.UserInputChecker.checkInput;
import static util.UserInputChecker.setCalculated;
import static util.UserInputChecker.setInitial;
import static util.Util.*;

import java.util.ArrayList;

public class PolygonCalculator extends Thread {
	double corners, side, apothem, circumference, area, radius;
	boolean found = false, before = false, calculated = false;
	MyFrame myFrame;

	public PolygonCalculator(double corners, double side, double apothem,
			double radius, double circumference, double area,
			final MyFrame myFrame) {
		this.myFrame = myFrame;
		this.corners = corners;
		this.side = side;
		this.apothem = apothem;
		this.radius = radius;
		this.circumference = circumference;
		this.area = area;
		setInitial(corners, side, apothem, circumference, area, radius);
		start();
	}

	public PolygonCalculator(double corners, double side, double apothem,
			double radius, double circumference, double area) {
		this.corners = corners;
		this.side = side;
		this.apothem = apothem;
		this.radius = radius;
		this.circumference = circumference;
		this.area = area;
	}

	public void run() {
		calculateRegular();
		finish();
	}

	private void finish() {
		side = roundToDecimals(side, 2);
		corners = roundToDecimals(corners, 2);
		apothem = roundToDecimals(apothem, 2);
		radius = roundToDecimals(radius, 2);
		circumference = roundToDecimals(circumference, 2);
		area = roundToDecimals(area, 2);
		if (myFrame != null) {
			setCalculated(corners, side, apothem, circumference, area, radius);
			if (checkInput()) {
				myFrame.setDataPanel(new PolygonOutputGui(corners, side,
						apothem, radius, circumference, area), "POLYGON_OUTPUT");
			} else {
				new ErrorMessage("Check input");
			}
		}
	}

	private void calculateRegular() {
		do {
			found = false;
			before = false;
			calculated = false;

			before = corners != 0;
			calculateRegularCorners();
			if (!before && found) {
				calculated = true;
			}

			before = side != 0;
			calculateRegularSide();
			if (!before && found) {
				calculated = true;
			}

			before = apothem != 0;
			calculateRegularApothem();
			if (!before && found) {
				calculated = true;
			}

			before = radius != 0;
			calculateRegularRadius();
			if (!before && found) {
				calculated = true;
			}

			before = circumference != 0;
			calculateRegularCircumference();
			if (!before && found) {
				calculated = true;
			}

			before = area != 0;
			calculateRegularArea();
			if (!before && found) {
				calculated = true;
			}
		} while (calculated);
	}

	private void calculateRegularCorners() {
		if (circumference != 0 && side != 0) {
			corners = circumference / side;
			found = true;
		}
	}

	private void calculateRegularRadius() {
		if (corners != 0) {
			if (area != 0) {
				radius = Math.sqrt((2 * area)
						/ (corners * Math.sin(Math.toRadians(360 / corners))));
				found = true;
			} else if (circumference != 0) {
				radius = Math
						.sqrt((2 * Math.pow(circumference, 2))
								/ (Math.pow(corners, 2)
										* 4
										* Math.tan(Math
												.toRadians(180 / corners)) * Math
											.sin(Math.toRadians(360 / corners))));
				found = true;
			} else if (side != 0) {
				radius = Math.sqrt((2 * Math.pow(side, 2))
						/ (4 * Math.tan(Math.toRadians(180 / corners)) * Math
								.sin(Math.toRadians(360 / corners))));
				found = true;
			} else if (apothem != 0) {
				radius = Math.sqrt((Math.pow(apothem, 2)
						* Math.tan(Math.toRadians(180 / corners)) * 2)
						/ Math.sin(Math.toRadians(360 / corners)));
				found = true;
			}
		}
	}

	private void calculateRegularApothem() {
		if (corners != 0) {
			if (area != 0) {
				apothem = Math.sqrt(area
						/ (corners * Math.tan(Math.toRadians(180 / corners))));
				found = true;
			} else if (circumference != 0) {
				apothem = circumference
						/ (corners * 2 * Math.sqrt(Math.tan(Math
								.toRadians(180 / corners))
								* Math.tan(Math.toRadians(180 / corners))));
				found = true;
			} else if (radius != 0) {
				apothem = radius
						/ (Math.sqrt((Math.tan(Math.toRadians(180 / corners)) * 2)
								/ Math.sin(Math.toRadians(360 / corners))));
				found = true;
			} else if (side != 0) {
				apothem = side
						/ (2 * Math
								.sqrt(Math.tan(Math.toRadians(180 / corners))
										* Math.tan(Math
												.toRadians(180 / corners))));
				found = true;
			}
		}
	}

	private void calculateRegularCircumference() {
		if (corners != 0) {
			if (side != 0) {
				circumference = corners * side;
				found = true;
			} else if (area != 0) {
				circumference = Math.sqrt(area * 4
						* Math.tan(Math.toRadians(180 / corners)) * corners);
				found = true;
			} else if (radius != 0) {
				circumference = Math.sqrt((Math.pow(radius, 2)
						* Math.pow(corners, 2) * 4
						* Math.sin(Math.toRadians(360 / corners)) * Math
						.tan(Math.toRadians(180 / corners))) / 2);
				found = true;
			} else if (apothem != 0) {
				circumference = Math.sqrt(Math.pow(apothem, 2)
						* Math.pow(corners, 2) * 4
						* Math.tan(Math.toRadians(180 / corners))
						* Math.tan(Math.toRadians(180 / corners)));
				found = true;
			}
		}
	}

	private void calculateRegularSide() {
		if (corners != 0) {
			if (circumference != 0) {
				side = circumference / corners;
			} else if (area != 0) {
				side = Math.sqrt((area * 4 * Math.tan(Math
						.toRadians(180 / corners))) / corners);
				found = true;
			} else if (radius != 0) {
				side = Math.sqrt((Math.pow(radius, 2) * 4
						* Math.sin(Math.toRadians(360 / corners)) * Math
						.tan(Math.toRadians(180 / corners))) / 2);
				found = true;
			} else if (apothem != 0) {
				side = apothem
						* 2
						* Math.sqrt(Math.tan(Math.toRadians(180 / corners))
								* Math.tan(Math.toRadians(180 / corners)));
				found = true;
			}
		}
	}

	private void calculateRegularArea() {
		if (corners != 0) {
			if (side != 0) {
				area = (Math.pow(side, 2) * corners)
						/ (4 * Math.tan(Math.toRadians(180 / corners)));
				found = true;
			} else if (radius != 0) {
				area = (Math.pow(radius, 2) * corners * Math.sin(Math
						.toRadians(360 / corners))) / 2;
				found = true;
			} else if (apothem != 0) {
				area = (Math.pow(apothem, 2) * corners * Math.tan(Math
						.toRadians(180 / corners)));
				found = true;
			} else if (circumference != 0) {
				area = (Math.pow(circumference, 2) / corners)
						/ (4 * Math.tan(Math.toRadians(180 / corners)));
				found = true;
			}
		}
	}
}
